﻿using System.ComponentModel;
using System.Runtime.CompilerServices;
using System;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.IO.Ports;
using System.Management;
using System.Collections.Generic;
using ChatGPT_SerialPortDemo.Bussinesses;

namespace ChatGPT_SerialPortDemo.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        public ObservableCollection<SerialPortInfo> AvailablePorts { get; } = new ObservableCollection<SerialPortInfo>();

        private SerialPortInfo _selectSerialPortInfo;
        public SerialPortInfo SelectSerialPortInfo
        {
            get { return _selectSerialPortInfo; }
            set { _selectSerialPortInfo = value; OnPropertyChanged(nameof(SelectSerialPortInfo)); }
        }


        //  波特率
        public List<int> BaudRates { get; } = new List<int>
        {
            9600,
            19200,
            38400,
            57600,
            115200,
            230400,
            460800,
            921600
        };

        private int _selectedBaudRate = 57600;
        public int SelectedBaudRate
        {
            get { return _selectedBaudRate; }
            set
            {
                _selectedBaudRate = value;
                OnPropertyChanged(nameof(SelectedBaudRate));
            }
        }

        //  数据位
        public List<int> DataBits { get; } = new List<int> { 5, 6, 7, 8 };
        private int _selectedDataBits = 8;
        public int SelectedDataBits
        {
            get { return _selectedDataBits; }
            set
            {
                if (_selectedDataBits != value)
                {
                    _selectedDataBits = value;
                    OnPropertyChanged(nameof(SelectedDataBits));
                }
            }
        }

        //  校验位
        public ObservableCollection<Parity> ParityOptions { get; } = new ObservableCollection<Parity> { Parity.None, Parity.Odd, Parity.Even };
        private Parity _selectedParity = Parity.None;
        public Parity SelectedParity
        {
            get { return _selectedParity; }
            set
            {
                if (_selectedParity != value)
                {
                    _selectedParity = value;
                    OnPropertyChanged(nameof(SelectedParity));
                }
            }
        }

        //  停止位
        public ObservableCollection<StopBits> StopBitOptions { get; } = new ObservableCollection<StopBits> { StopBits.One, StopBits.OnePointFive, StopBits.Two };
        private StopBits _selectedStopBit = StopBits.One;
        public StopBits SelectedStopBit
        {
            get { return _selectedStopBit; }
            set
            {
                if (_selectedStopBit != value)
                {
                    _selectedStopBit = value;
                    OnPropertyChanged(nameof(SelectedStopBit));
                }
            }
        }

        //  流控
        public ObservableCollection<Handshake> FlowControlOptions { get; } = new ObservableCollection<Handshake> { 
            Handshake.None
            , Handshake.RequestToSend
            , Handshake.RequestToSendXOnXOff
            , Handshake.XOnXOff
        };

        private Handshake _selectedFlowControl = Handshake.None;
        public Handshake SelectedFlowControl
        {
            get { return _selectedFlowControl; }
            set
            {
                if (_selectedFlowControl != value)
                {
                    _selectedFlowControl = value;
                    OnPropertyChanged(nameof(SelectedFlowControl));
                }
            }
        }

        //  参数设置
        public enum DataMode
        {
            ASCII,
            Hex
        }

        //  接收参数设置

        private DataMode _selectedRecvDataMode;
        public DataMode SelectedRecvDataMode
        {
            get { return _selectedRecvDataMode; }
            set
            {
                if (_selectedRecvDataMode != value)
                {
                    _selectedRecvDataMode = value;
                    OnPropertyChanged(nameof(SelectedRecvDataMode));
                }
            }
        }
        private bool _isAutoWrap;
        public bool IsAutoWrap
        {
            get { return _isAutoWrap; }
            set
            {
                if (_isAutoWrap != value)
                {
                    _isAutoWrap = value;
                    OnPropertyChanged(nameof(IsAutoWrap));
                }
            }
        }

        private bool _isShowSent;
        public bool IsShowSent
        {
            get { return _isShowSent; }
            set
            {
                if (_isShowSent != value)
                {
                    _isShowSent = value;
                    OnPropertyChanged(nameof(IsShowSent));
                }
            }
        }

        private bool _isShowTime;
        public bool IsShowTime
        {
            get { return _isShowTime; }
            set
            {
                if (_isShowTime != value)
                {
                    _isShowTime = value;
                    OnPropertyChanged(nameof(IsShowTime));
                }
            }
        }

        //  发送参数设置
        private DataMode _selectedSendDataMode;
        public DataMode SelectedSendDataMode
        {
            get { return _selectedSendDataMode; }
            set
            {
                if (_selectedSendDataMode != value)
                {
                    _selectedSendDataMode = value;
                    OnPropertyChanged(nameof(SelectedSendDataMode));
                }
            }
        }

        private bool _isSendLineByLine;
        public bool IsSendLineByLine
        {
            get { return _isSendLineByLine; }
            set
            {
                if (_isSendLineByLine != value)
                {
                    _isSendLineByLine = value;
                    OnPropertyChanged(nameof(IsSendLineByLine));
                }
            }
        }

        private int _lineByLineInterval;
        public int LineByLineInterval
        {
            get { return _lineByLineInterval; }
            set
            {
                if (_lineByLineInterval != value)
                {
                    _lineByLineInterval = value;
                    OnPropertyChanged(nameof(LineByLineInterval));
                }
            }
        }

        private bool _isAutoResend;
        public bool IsAutoResend
        {
            get { return _isAutoResend; }
            set
            {
                if (_isAutoResend != value)
                {
                    _isAutoResend = value;
                    OnPropertyChanged(nameof(IsAutoResend));
                }
            }
        }

        private int _resendInterval;
        public int ResendInterval
        {
            get { return _resendInterval; }
            set
            {
                if (_resendInterval != value)
                {
                    _resendInterval = value;
                    OnPropertyChanged(nameof(ResendInterval));
                }
            }
        }

        //  串口管理
        private SerialPortManager _serialPortManager;
        public bool IsConnected
        {
            get { return _serialPortManager.IsConnected; }
        }

        //  数据相关
        private string _receivedData;
        public string ReceivedData
        {
            get { return _receivedData; }
            set
            {
                _receivedData = value;
                OnPropertyChanged(nameof(ReceivedData));
            }
        }


        private string _sentData;
        public string SentData
        {
            get { return _sentData; }
            set
            {
                _sentData = value;
                OnPropertyChanged(nameof(SentData));
            }
        }

        //  历史数据记录
        private ObservableCollection<string> _history = new ObservableCollection<string>();
        public ObservableCollection<string> History
        {
            get { return _history; }
            set
            {
                _history = value;
                OnPropertyChanged(nameof(History));
            }
        }


        //  命令行设置

        public ICommand ConnectCommand { get; }
        public ICommand ClosePortCommand { get; }
        public ICommand SendDataCommand { get; }
        public ICommand SelectHistoryCommand { get; }


        public MainViewModel()
        {
            ConnectCommand = new RelayCommand<object>(Connect);
            ClosePortCommand = new RelayCommand<object>(ClosePort);
            SendDataCommand = new RelayCommand<object>(SendData);
            SelectHistoryCommand = new RelayCommand<object>(SelectHistory);

            _serialPortManager = new SerialPortManager();
            _serialPortManager.ConnectionStateChanged += OnConnectionStateChanged;
            _serialPortManager.DataReceived += OnDataReceived;

            // 获取可用串口并添加到ObservableCollection中
            LoadAvailablePorts();
            SettingsManager.Instance.LoadSettings(this);
            if (History.Count > 0)
            {
                SelectedItem = History[0];
                SentData = SelectedItem;
            }
        }

        private void OnDataReceived(object sender, byte[] data)
        {
            string result = TransformData(data, SelectedRecvDataMode);
            ShowReceivedData("[收]", result);


            //  自动重发
            if (ResendInterval < 0)
            {
                ResendInterval = 10;
            }
            if (IsAutoResend)
            {
                System.Threading.Thread.Sleep(ResendInterval);
                ManualSendData();
            }
        }

        private void ShowReceivedData(string flag, string data)
        {
            string showInfo = $"{flag}";
            if(IsShowTime)
            {
                showInfo += $"{DateTime.Now.ToString("HH:mm:ss.fff")}>>  ";
            }

            //showInfo += TransformData(data, SelectedRecvDataMode);
            showInfo += data;
            if (IsAutoWrap)
            {
                showInfo += "\r";
            }
            ReceivedData = ReceivedData + showInfo;
        }

        private void OnConnectionStateChanged(object sender, bool flag)
        {
            OnPropertyChanged(nameof(IsConnected));
        }

        private void LoadAvailablePorts()
        {
            try
            {
                List<string> ports = new List<string>();
                //  获取Port
                string propKey = "Name";
                using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_PnPEntity"))
                {
                    var hardInfos = searcher.Get();
                    foreach (var hardInfo in hardInfos)
                    {
                        if (hardInfo != null
                            && hardInfo.Properties[propKey].Value != null
                            && hardInfo.Properties[propKey].Value.ToString().Contains("COM"))
                        {
                            ports.Add(hardInfo.Properties[propKey].Value.ToString());
                        }

                    }
                    searcher.Dispose();
                }
                //  串口号列表
                int insertComPort = 0;
                Dictionary<string, string> selectedList = new Dictionary<string, string>();
                for (int i = 1; i < 20; i++)
                {
                    string keyComName = "COM" + i;
                    string valueComName = "COM" + i;

                    foreach (var portStateName in ports)
                    {
                        if (portStateName.Contains("(" + keyComName + ")"))
                        {
                            valueComName = portStateName;
                            insertComPort = i - 1;
                        }
                    }
                    selectedList.Add(keyComName, valueComName);
                }
                //  数据绑定
                foreach (var item in selectedList)
                {
                    if (item.Key != item.Value)
                    {
                        AvailablePorts.Add(new SerialPortInfo(item.Key, item.Value));
                    }
                }
                //  默认选择最后一个有效串口
                if(AvailablePorts.Count > 0)
                {
                    SelectSerialPortInfo = AvailablePorts[AvailablePorts.Count - 1];
                }
            }
            catch (Exception ex)
            {
                // 处理异常
            }
        }


        private void Connect(object parameter)
        {
            // 连接串口逻辑
            bool isConnected = _serialPortManager.Connect(
                SelectSerialPortInfo.PortName,
                SelectedBaudRate,
                SelectedParity,
                SelectedDataBits,
                SelectedStopBit,
                SelectedFlowControl
            );
        }

        private void ClosePort(object parameter)
        {
            // 关闭串口逻辑
            _serialPortManager.Disconnect();
        }

        private byte[] TransformData(string originDat, DataMode mode)
        {
            List<byte> result = new List<byte>();
            switch (mode)
            {
                case DataMode.ASCII:
                    byte[] dat = System.Text.Encoding.ASCII.GetBytes(originDat);
                    //string transDat = BitConverter.ToString(dat).Replace("-", "");
                    result.AddRange(dat);
                    break;
                case DataMode.Hex:
                    byte[] dat_Hex = strToToHexByte(originDat);
                    result.AddRange(dat_Hex);
                    break;
            }
            return result.ToArray();
        }

        private string TransformData(byte[] originDat, DataMode mode)
        {
            string result = "";
            switch (mode)
            {
                case DataMode.ASCII:
                    result = System.Text.Encoding.ASCII.GetString(originDat);
                    break;
                case DataMode.Hex:
                    result = BitConverter.ToString(originDat).Replace("-", " ");
                    break;
            }
            return result;
        }

        //  
        /// 字符串转16进制字节数组 
        ///   
        private static byte[] strToToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            }
            return returnBytes;
        }


        private void SendData(object parameter)
        {
            if (!History.Contains(SentData))
            {
                History.Add(SentData);
            }
            SettingsManager.Instance.SaveSettings(this);
            ManualSendData();
        }
        private void ManualSendData()
        {
            List<string> sendList = new List<string>();
            if(LineByLineInterval < 0)
            {
                LineByLineInterval = 0;
            }

            if(IsSendLineByLine)
            {
                string[] lines = SentData.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                sendList.AddRange(lines);
            } else
            {
                sendList.Add(SentData);
            }

            foreach (string line in sendList)
            {
                byte[] hexData = TransformData(line, SelectedSendDataMode);
                _serialPortManager.SendData(hexData);
                if(IsShowSent)
                {
                    ShowReceivedData("[发]", line);
                }
                // 可以在此处处理每行数据发送成功后的逻辑
                if (sendList.Count > 1)
                {
                    System.Threading.Thread.Sleep(LineByLineInterval);
                }
            }
        }

        //  历史发送指令
        public string SelectedItem { get; set; }
        private void SelectHistory(object obj)
        {
            SentData = SelectedItem;
        }
    }

    public class SerialPortInfo
    {
        public string PortName { get; }
        public string PortDescription { get; }

        public SerialPortInfo(string portName, string portDescription)
        {
            PortName = portName;
            PortDescription = portDescription;
        }

        public override string ToString()
        {
            return $"{PortName} ({PortDescription})";
        }
    }
}
